package com.wt.admin.service.sys.impl;

import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.jwt.JWT;
import com.aizuda.easy.security.code.BasicCode;
import com.aizuda.easy.security.exp.impl.BasicException;
import com.aizuda.easy.security.properties.SecurityProperties;
import com.aizuda.easy.security.server.EasySecurityServer;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wt.admin.code.sys.SysUser1000;
import com.wt.admin.config.CiphertextTypeHandler;
import com.wt.admin.config.cache.Cache;
import com.wt.admin.config.prop.IndexProp;
import com.wt.admin.domain.dto.sys.SysUserInfoUpdateDTO;
import com.wt.admin.domain.dto.sys.SysUserLoginDTO;
import com.wt.admin.domain.dto.sys.SysUserPasswordDTO;
import com.wt.admin.domain.entity.sys.SysMenuEntity;
import com.wt.admin.domain.entity.sys.SysRoleEntity;
import com.wt.admin.domain.entity.sys.SysUserEntity;
import com.wt.admin.domain.vo.sys.SysRoleVO;
import com.wt.admin.domain.vo.sys.SysUserListVO;
import com.wt.admin.domain.vo.sys.UserVO;
import com.wt.admin.mapper.sys.SysUserMapper;
import com.wt.admin.service.sys.SysRoleService;
import com.wt.admin.service.sys.SysUserService;
import com.wt.admin.util.AssertUtil;
import com.wt.admin.util.PageUtil;
import org.springframework.stereotype.Service;

import jakarta.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUserEntity> implements SysUserService, EasySecurityServer {

    @Resource
    private SysUserMapper sysUserMapper;
    @Resource
    SecurityProperties securityProperties;
    @Resource
    SysRoleService sysRoleService;
    Map<String,String> codeMap = new ConcurrentHashMap<>();
    @Resource
    IndexProp indexProp;
    @Resource
    Cache<String,UserVO> userCache;


    @Override
    public UserVO login(SysUserLoginDTO data) {
        AssertUtil.objIsNull(data.getAccount(), SysUser1000.USER_CODE_1000);
        AssertUtil.objIsNull(data.getPassword(), SysUser1000.USER_CODE_1000);
//        AssertUtil.objIsNull(data.getCode(), SysUserCode.USER_CODE_1001);
//        AssertUtil.Str.isEmpty(codeMap.get(data.getCode()), SysUserCode.USER_CODE_1002);
        data.setPassword(encryptionPassword(data.getPassword(), data.getAccount()));
        data.setAccount(CiphertextTypeHandler.encrypt(data.getAccount()));
        SysUserEntity sysUserEntity = sysUserMapper.findByAccountAndPassword(data);
        AssertUtil.objIsNull(sysUserEntity, SysUser1000.USER_CODE_1003);
        SysRoleVO role = sysRoleService.findRoleId(sysUserEntity.getRoleId());
        AssertUtil.objIsNull(role, BasicCode.BASIC_CODE_403);
        String token = JWT.create()
                .setPayload("id",sysUserEntity.getId())
                .setPayload("exp", System.currentTimeMillis()+indexProp.getKeys().getTokenExpire())
                .setKey(securityProperties.getSecretKey().getBytes())
                .sign();
        UserVO user = UserVO.builder()
                .id(sysUserEntity.getId())
                .nickName(sysUserEntity.getNickName())
                .email(sysUserEntity.getEmail())
                .role(role)
                .token(token).build();
        userCache.put(user.getToken(),user);
        return user;
    }

    @Override
    public Map<String,Object> code() {
        String s = RandomUtil.randomString(5);
        codeMap.put(s,s);
        Thread thread = new Thread(() -> {
            ThreadUtil.sleep(60 * 1000);
            codeMap.remove(s);
        });
        thread.setName("登录Code码有效期");
        thread.start();
        return new HashMap<String,Object>(){{
            put("ret", new HashMap<String,Object>(){{
                put("code", 200);
                put("message", "验证成功");
            }});
            put("data", s);
        }};
    }

    @Override
    public SysUserEntity updatePassword(SysUserPasswordDTO data) {
        AssertUtil.Str.isEmpty(data.getPassword(), SysUser1000.USER_CODE_1004);
        AssertUtil.Str.isEmpty(data.getOkPassword(), SysUser1000.USER_CODE_1004);
        AssertUtil.Str.isEQ(data.getPassword(),data.getOkPassword(), SysUser1000.USER_CODE_1009);
        AssertUtil.objIsNull(data.getId(), SysUser1000.USER_CODE_1005);
        SysUserEntity sysUserEntity = sysUserMapper.selectById(data.getId());
        AssertUtil.objIsNull(sysUserEntity, BasicCode.BASIC_CODE_402);
        String s = encryptionPassword(data.getPassword(), sysUserEntity.getAccount());
        sysUserEntity.setPassword(s);
        updateById(sysUserEntity);
        return sysUserEntity;
    }

    @Override
    public SysUserEntity del(SysUserEntity data) {
        AssertUtil.objIsNull(data.getId(), SysUser1000.USER_CODE_1005);
        sysUserMapper.deleteById(data);
        return null;
    }

    @Override
    public SysUserEntity info(UserVO user) {
        SysUserEntity sysUserEntity = sysUserMapper.selectById(user.getId());
        AssertUtil.objIsNull(sysUserEntity, BasicCode.BASIC_CODE_402);
        return sysUserEntity;
    }

    @Override
    public SysUserEntity updateInfo(SysUserInfoUpdateDTO data) {
        AssertUtil.objIsNull(data.getId(), SysUser1000.USER_CODE_1005);
        AssertUtil.Str.isEmpty(data.getNickName(), SysUser1000.USER_CODE_1007);
        AssertUtil.Str.isEmpty(data.getEmail(), SysUser1000.USER_CODE_1008);
        SysUserEntity sysUserEntity = sysUserMapper.selectById(data.getId());
        if(!StrUtil.isEmpty(data.getPassword())) {
            AssertUtil.Str.isEmpty(data.getPassword(), SysUser1000.USER_CODE_1004);
            AssertUtil.Str.isEmpty(data.getOkPassword(), SysUser1000.USER_CODE_1004);
            AssertUtil.Str.isEQ(data.getPassword(),data.getOkPassword(), SysUser1000.USER_CODE_1009);
            sysUserEntity.setPassword(encryptionPassword(data.getPassword(), sysUserEntity.getAccount()));
        }
        sysUserEntity.setEmail(data.getEmail());
        sysUserEntity.setNickName(data.getNickName());
        updateById(sysUserEntity);
        return null;
    }

    @Override
    public SysUserListVO find(PageUtil.PageDTO<SysUserEntity> data) {
        AssertUtil.objIsNull(data.getData(),BasicCode.BASIC_CODE_99999);
        PageUtil.PageVO<SysUserEntity> pag = PageUtil.findPage(data, (page) -> sysUserMapper.find(page, data.getData()));
        // 查询所有角色
        List<SysRoleEntity> sysRoleEntities = sysRoleService.findAll();
        SysUserListVO sysUserListVO = new SysUserListVO();
        sysUserListVO.setPage(pag);
        sysUserListVO.setRoles(sysRoleEntities);
        return sysUserListVO;
    }

    @Override
    public SysUserEntity edit(SysUserEntity data) {
        AssertUtil.Str.isEmpty(data.getAccount(), SysUser1000.USER_CODE_1006);
        AssertUtil.Str.isEmpty(data.getPassword(), SysUser1000.USER_CODE_1004);
        AssertUtil.Str.isEmpty(data.getNickName(), SysUser1000.USER_CODE_1007);
        AssertUtil.Str.isEmpty(data.getEmail(), SysUser1000.USER_CODE_1008);
        if(ObjectUtil.isEmpty(data.getId())) {
            data.setPassword(encryptionPassword(data.getPassword(), data.getAccount()));
        }
        saveOrUpdate(data);
        return data;
    }

    @Override
    public Object getAuthUser(String token) throws BasicException {
        JWT jwt = JWT.of(token);
        // 验证
        if(!jwt.setKey(securityProperties.getSecretKey().getBytes()).verify()){
            throw new BasicException(BasicCode.BASIC_CODE_99986);
        }
        return userCache.get(token);
    }

    @Override
    public List<String> getAuthorizeUrl(String token){
        return userCache.get(token).getRole().getMenus().stream().map(SysMenuEntity::getPath)
                .collect(Collectors.toList());
    }

    private String encryptionPassword(String password,String account){
        return SecureUtil.md5(password+account);
    }

}
